/*************************************
 * Created by WebStorm
 * Author : 艾尼亚尔·毛拉吾提
 * QQ : 524155792  WeChat : ainiyar0124
 * Created Time :2024/2/5 18:48
 Desc :
 **************************************/
import axios from 'axios';
import type {AxiosInstance, AxiosResponse, AxiosRequestConfig} from 'axios';
import {CreateAxiosOptions, RequestOptions, Result} from "./type.ts";
import {cloneDeep} from 'lodash-es';
import {isFunction} from '@/util/is.ts';
import {AxiosCanceler} from './AxiosCanceler.ts';
import {checkStatus} from "./checkStatus.ts";

export class VAxios {
    private axiosInstance: AxiosInstance;
    private readonly options: CreateAxiosOptions;

    constructor(options: CreateAxiosOptions) {
        this.options = options;
        this.axiosInstance = axios.create(options);
        this.setupInterceptors();
    }

    request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
        let conf: AxiosRequestConfig = cloneDeep(config);
        const transform = this.getTransform();
        const {requestOptions} = this.options;
        const opt: RequestOptions = Object.assign({}, requestOptions, options);
        const {beforeRequestHook, transformResponseData, requestCatch} = transform || {};

        if (beforeRequestHook && isFunction(beforeRequestHook)) {
            conf = beforeRequestHook(conf, opt);
        }
        //这里重新 赋值成最新的配置
        // @ts-ignore
        conf.requestOptions = opt;
        return new Promise((resolve, reject) => {
            this.axiosInstance
                .request<any, AxiosResponse<Result>>(conf)
                .then((res: AxiosResponse<Result>) => {
                    // 请求是否被取消
                    const isCancel = axios.isCancel(res);
                    if (transformResponseData && isFunction(transformResponseData) && !isCancel) {
                        try {
                            const ret = transformResponseData(res, opt);
                            resolve(ret);
                        } catch (err) {
                            reject(err || new Error('request error!'));
                        }
                        return;
                    }
                    resolve(res as unknown as Promise<T>);
                })
                .catch((e: Error) => {
                    if (requestCatch && isFunction(requestCatch)) {
                        reject(requestCatch(e));
                        return;
                    }
                    reject(e);
                });
        });
    }

    private getTransform() {
        const {transformAxios} = this.options;
        return transformAxios;
    }

    /**
     * @description: 拦截器配置
     */
    private setupInterceptors() {
        const transform = this.getTransform();
        if (!transform) {
            return;
        }
        const {
            requestInterceptors,
            requestInterceptorsCatch,
            responseInterceptors,
            responseInterceptorsCatch,
        } = transform;
        const axiosCanceler = new AxiosCanceler();
        // 请求拦截器配置处理
        this.axiosInstance.interceptors.request.use((config: any) => {
            // @ts-ignore
            const {headers: {ignoreCancelToken}} = config;
            const ignoreCancel =
                ignoreCancelToken !== undefined
                    ? ignoreCancelToken
                    : this.options.requestOptions?.ignoreCancelToken;

            !ignoreCancel && axiosCanceler.addPending(config);
            if (requestInterceptors && isFunction(requestInterceptors)) {
                config = requestInterceptors(config, this.options);
            }
            return config;
        }, undefined);
        // 请求拦截器错误捕获
        requestInterceptorsCatch && isFunction(requestInterceptorsCatch) && this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch);
        this.axiosInstance.interceptors.response.use((res:  AxiosResponse<any, any>): any => {
            res && axiosCanceler.removePending(res.config);
            if (responseInterceptors && isFunction(responseInterceptors)) {
                res = responseInterceptors(res);
            }
            if (res.data.code === 200 || res.data.code === 400){
                return res;
            }else {
                checkStatus(res.data.code, res.data.message)
                return  false;
            }
        },undefined);
        // 响应结果拦截器错误捕获
        responseInterceptorsCatch && isFunction(responseInterceptorsCatch) && this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch);
    }

}